<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>下属行政区查询</title>
</head>
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&libraries=service&key=MZQBZ-EKRKU-SK5VS-2DA2P-GIL6V-BUBEL"></script>
<style type="text/css">
    html,
    body {
        height: 100%;
        margin: 0px;
        padding: 0px;
    }

    #container {
        width: 100%;
        height: 100%;
    }

    #panel {
        position: absolute;
        background: #FFF;
        width:350px;
        padding: 20px;
        z-index: 9999;
        top: 30px;
        left: 30px;
    }


    .options {
        position: relative;
        display: flex;
        align-items: center;
        width: 100%;
        height: 2rem;
    }
    
    .title {
        width: 3rem;
        text-align: justify;
        display: inline-block;
        text-align-last: justify;
    }

        

</style>

<body>
    <div id="container"></div>
    <div id="panel">
        <h4>下属行政区查询</h4>
        <div class="input-item">
            <div class="title">省市区</div>
            <select id='province' style="width:200px" onchange='search(this)'></select>
        </div>
        <div class="input-item">
            <div class="title">地级市</div>
            <select id='city' style="width:200px" onchange='search(this)'></select>
        </div>
        <div class="input-item">
            <div class="title">区县</div>
            <select id='district' style="width:200px" onchange='search(this)'></select>
        </div>
        <div class="input-item">
            <div class="title">街道</div>
            <select id='street' style="width:200px" onchange='search(this)'></select>
        </div>
    </div>

</body>

</html>

<script type="text/javascript">
var map = new TMap.Map('container', {
  zoom: 8,
  center: new TMap.LatLng(40, 116),
});
var provinceSelect = document.getElementById('province');
var citySelect = document.getElementById('city');
var districtSelect = document.getElementById('district');
var areaSelect = document.getElementById('street');
var provinceList = [];
var cityList = [];
var districtList = [];
var areaList = [];
var district = new TMap.service.District({
  // 新建一个行政区划类
  polygon: 2, // 返回行政区划边界的类型
});
var polygons = new TMap.MultiPolygon({
  map: map,
  geometries: [],
});

district.getChildren().then((result) => {
  // 获取省市区列表及其边界信息
  provinceList = result.result[0];
  provinceSelect.add(new Option('---请选择---', null));
  provinceList.forEach((province, index) => {
    provinceSelect.add(new Option(province.fullname, index));
  });
  citySelect.innerHTML = '';
  districtSelect.innerHTML = '';
  areaSelect.innerHTML = '';
});

function search(selector) {
  if (selector.id === 'province' && selector.value) {
    citySelect.innerHTML = '';
    districtSelect.innerHTML = '';
    areaSelect.innerHTML = '';
    citySelect.add(new Option('---请选择---', null));
    district
      .getChildren({ id: provinceList[selector.value].id })
      .then((result) => {
        // 根据选择的省市区获取其下级行政区划及其边界
        cityList = result.result[0];
        cityList.forEach((city, index) => {
          citySelect.add(new Option(city.fullname, index));
        });
      });
    drawPolygon(
      provinceList[selector.value].id,
      provinceList[selector.value].polygon
    ); // 根据所选区域绘制边界
  } else if (selector.id === 'city' && selector.value) {
    districtSelect.innerHTML = '';
    areaSelect.innerHTML = '';
    districtSelect.add(new Option('---请选择---', null));
    district.getChildren({ id: cityList[selector.value].id }).then((result) => {
      // 根据选择的地级市或直辖市区获取其下级行政区划及其边界
      if (result.result[0].length > 0 && result.result[0][0].id.length > 6) {
        // 直辖市的区的下级即为街道级，故略过一级
        districtList = [];
        districtSelect.innerHTML = '';
        districtSelect.add(new Option('---------', null));
        areaList = result.result[0];
        areaSelect.add(new Option('---请选择---', null));
        areaList.forEach((district, index) => {
          areaSelect.add(new Option(district.fullname, index));
        }); // 根据所选区域绘制边界
      } else {
        // 非直辖市的地级市之下有区县级
        districtList = result.result[0];
        districtList.forEach((district, index) => {
          districtSelect.add(new Option(district.fullname, index));
        });
      }
    });
    drawPolygon(cityList[selector.value].id, cityList[selector.value].polygon);
    // 根据所选区域绘制边界
  } else if (selector.id === 'district' && selector.value) {
    areaSelect.innerHTML = '';
    district
      .getChildren({ id: districtList[selector.value].id })
      .then((result) => {
        // 根据选择的区县获取其下级行政区划及位置
        areaList = result.result[0];
        areaList.forEach((area, index) => {
          areaSelect.add(new Option(area.fullname, index));
        });
      });
    areaSelect.add(new Option('---请选择---', null));
    drawPolygon(
      districtList[selector.value].id,
      districtList[selector.value].polygon
    );
  } else if (selector.id === 'street' && selector.value) {
    map.setCenter(areaList[selector.value].location);
    // 街道级仅提供位置信息不提供边界信息，故以设置地图中心代替边界绘制
  }
}
function drawPolygon(placeId, polygonArray) {
  // 根据多边形顶点坐标数组绘制多边形
  polygons.remove(polygons.getGeometries().map((item) => item.id));
  var bounds = [];
  var newGeometries = polygonArray.map((polygon, index) => {
    bounds.push(fitBounds(polygon));
    return {
      id: `${placeId}_${index}`,
      paths: polygon,
    };
  });
  bounds = bounds.reduce((a, b) => {
    return fitBounds([
      a.getNorthEast(),
      a.getSouthWest(),
      b.getNorthEast(),
      b.getSouthWest(),
    ]);
  });
  polygons.updateGeometries(newGeometries);
  map.fitBounds(bounds);
}
function fitBounds(latLngList) {
  // 由多边形顶点坐标数组计算能完整呈现该多边形的最小矩形范围
  if (latLngList.length === 0) {
    return null;
  }
  var boundsN = latLngList[0].getLat();
  var boundsS = boundsN;
  var boundsW = latLngList[0].getLng();
  var boundsE = boundsW;
  latLngList.forEach((point) => {
    point.getLat() > boundsN && (boundsN = point.getLat());
    point.getLat() < boundsS && (boundsS = point.getLat());
    point.getLng() > boundsE && (boundsE = point.getLng());
    point.getLng() < boundsW && (boundsW = point.getLng());
  });
  return new TMap.LatLngBounds(
    new TMap.LatLng(boundsS, boundsW),
    new TMap.LatLng(boundsN, boundsE)
  );
}
</script>